package com.ys.http.upload;

import android.util.Log;

import com.ys.http.api.UploadLoadApi;
import com.ys.http.body.UploadRequestBody;
import com.ys.http.entry.Resp;
import com.ys.http.network.Body;
import com.ys.http.network.Callback;
import com.ys.http.network.HttpHelper;
import com.ys.http.network.SchedulerProvider;
import com.ys.http.network.MultipartBuilder;
import com.ys.http.utils.MimeTypeUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.reactivex.disposables.Disposable;


/***
 * 文件上传方法
 * 链式调用
 *new UploadTask.Builder()
 * set
 * set
 * setOnUploadListener
 *  .build();
 *   mTask.start();
 *
 *   停止方法
 *   mTask.stop();
 *
 */
public class UploadTask {

    private static final String TAG = "uploadTask";
    private final String mUploadUrl;
    private final Body mBody;
    private final Map<String, String> headers;
    private List<UploadRequestBody> bodies;

    private final OnUploadListener mListener;
    private Disposable mDisposable;

    private UploadTask(String uploadUrl, Body body, OnUploadListener listener) {
        this(uploadUrl, body, new HashMap<>(), listener);
    }

    private UploadTask(String uploadUrl, Body body, Map<String, String> headers, OnUploadListener listener) {
        this.mUploadUrl = uploadUrl;
        this.headers = headers;
        this.mBody = body;

        this.mListener = listener;
    }

    private UploadTask(String uploadUrl, Body body, Map<String, String> headers, List<UploadRequestBody> bodies, OnUploadListener listener) {
        this.mUploadUrl = uploadUrl;
        this.headers = headers;
        this.mBody = body;
        this.bodies = bodies;
        this.mListener = listener;
    }

    /**
     * 开始上传
     */
    public void start() {
        if (mUploadUrl == null) {
            Log.e(TAG, "uploadUrl is null");
            return;
        }
        stop();

        HttpHelper.getInstance()
                .createApi(UploadLoadApi.class)
                .upload(mUploadUrl, headers, mBody.body())
                .compose(SchedulerProvider.applyScheduler())
                .subscribe(new Callback<Resp<String>>() {

                    @Override
                    public void onSubscribe(Disposable d) {
                        mDisposable = d;
                    }

                    @Override
                    public void onSuccess(Resp<String> resp) {
                        if (mListener != null) {
                            mListener.onResp(resp);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        if (mListener != null) {
                            mListener.onFailure(e);
                        }
                    }
                });
    }

    public void stop() {
        if (mDisposable != null) {
            mDisposable.dispose();
            mDisposable = null;
        }
        if (bodies != null) {
            for (UploadRequestBody body : bodies) {
                body.disposable();
            }
        }
    }

    public static class Builder {
        private OnUploadListener listener;
        private String uploadUrl;
        private List<UploadRequestBody> bodys;

        private final Map<String, String> headerMap = new HashMap<>();
        private final MultipartBuilder builder = Body.newMultiBody();

        public Builder addHeader(String name, String value) {
            headerMap.put(name, value);
            return this;
        }

        public Builder addHeader(Map<String, String> headers) {
            if (headers != null) {
                Set<Map.Entry<String, String>> entries = headers.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    addHeader(entry.getKey(), entry.getValue());
                }
            }
            return this;
        }

        public Builder addParams(Map<String, String> params) {
            if (params != null) {
                Set<Map.Entry<String, String>> entries = params.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    addParams(entry.getKey(), entry.getValue());
                }
            }
            return this;
        }

        public Builder addParams(String name, String value) {
            builder.addParam(name, value);
            return this;
        }

        public Builder addParams(File file) {
            return addParams("files", file);
        }

        public Builder addParams(File file, String mediaType) {
            return addParams("files", file);
        }

        public Builder addParams(String name, File file) {
            addParams(name, file, MimeTypeUtils.getMimeType(file.getName()));
            return this;
        }

        public Builder addParams(String name, File file, String mediaType) {
            UploadRequestBody body = UploadRequestBody.create(file, mediaType);
            if (bodys == null) {
                bodys = new ArrayList<>();
            }
            bodys.add(body);
            builder.addParam(name, file.getName(), body);
            return this;
        }

        public Builder setUploadUrl(String url) {
            this.uploadUrl = url;
            return this;
        }

        public Builder setOnUploadListener(OnUploadListener listener) {
            this.listener = listener;
            return this;
        }

        public UploadTask build() {
            if (bodys != null) {
                for (UploadRequestBody body : bodys) {
                    body.setOnUploadListener(listener);
                }
            }
            return new UploadTask(uploadUrl, builder.build(), headerMap, bodys, listener);
        }
    }

}
